package com.borball.store.comp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.Timestamp;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JComponent;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableRowSorter;

import com.borball.store.dao.CardDAO;
import com.borball.store.dao.CompositeDAO;
import com.borball.store.domain.Card;
import com.borball.store.domain.Composite;
import com.borball.store.domain.User;
import com.borball.store.util.MaterialUtils;

import craky.component.CommonTableModel;
import craky.componentc.JCButton;
import craky.componentc.JCLabel;
import craky.componentc.JCMessageBox;
import craky.componentc.JCPopupMenu;
import craky.componentc.JCScrollTable;
import craky.componentc.JCTable;
import craky.componentc.JCTableHeader;
import craky.componentc.JCTextField;
import craky.keeper.EmptyComponent;
import craky.keeper.KeeperApp;
import craky.keeper.KeeperPane;
import craky.layout.LineLayout;

public class CardPane extends KeeperPane {

	private static final long serialVersionUID = 2583431180094797757L;

	private static final String CMD_INSERT = "Insert";

	private static final String CMD_MODIFY = "Modify";

	private static final String[] COLUMNS_NAME = { "产品名称", "单位", "备注", "创建时间" };

	protected KeeperApp keeper;

	protected User currentUser;

	protected CommonTableModel<Card> model;

	protected List<Card> data;

	protected Card currentData;

	protected Action insertAction, modifyAction, deleteAction, submitAction, cancelAction;

	protected JCTable table;

	protected JCPopupMenu popup;

	protected JComponent top, bottom, center;

	protected JComponent ecName, ecDesc, ecUnit;

	protected JCTextField cpName, cpUnit, cpDesc;

	private JCButton btnModify, btnDelete, btnInsert, btnSubmit, btnCancel;
	private CardDAO cardDAO = new CardDAO();
	CompositeDAO compositeDAO = new CompositeDAO();

	private boolean modifying;

	private int selectedIndex;

	public CardPane(KeeperApp keeper) {
		this.keeper = keeper;
		this.currentUser = keeper.getCurrentUser();

		this.selectedIndex = -1;

		load();
		initActions();
		initUI();
		resetTypes();
	}

	private void initActions() {
		insertAction = new AbstractAction("\u6DFB\u52A0") {
			private static final long serialVersionUID = 5056698643009336063L;

			public void actionPerformed(ActionEvent e) {
				insertOrModify(true);
			}
		};

		modifyAction = new AbstractAction("\u4FEE\u6539") {
			private static final long serialVersionUID = 8222836515926767063L;

			public void actionPerformed(ActionEvent e) {
				insertOrModify(false);
			}
		};

		deleteAction = new AbstractAction("\u5220\u9664") {
			private static final long serialVersionUID = -4608405524916997614L;

			public void actionPerformed(ActionEvent e) {
				delete();
			}
		};

		submitAction = new AbstractAction("\u786E\u5B9A") {
			private static final long serialVersionUID = 6989199497316998154L;

			public void actionPerformed(ActionEvent e) {
				submit();
			}
		};

		cancelAction = new AbstractAction("\u53D6\u6D88") {
			private static final long serialVersionUID = 6989199497316998154L;

			public void actionPerformed(ActionEvent e) {
				cancel();
			}
		};

		modifyAction.setEnabled(false);
		deleteAction.setEnabled(false);
	}

	private void initUI() {
		btnModify = new JCButton(modifyAction);
		btnDelete = new JCButton(deleteAction);
		btnInsert = new JCButton(insertAction);
		btnSubmit = new JCButton(submitAction);
		btnCancel = new JCButton(cancelAction);
		btnModify.setPreferredSize(new Dimension(-1, 21));
		btnDelete.setPreferredSize(btnModify.getPreferredSize());
		btnInsert.setPreferredSize(btnModify.getPreferredSize());
		btnSubmit.setPreferredSize(btnModify.getPreferredSize());
		btnCancel.setPreferredSize(btnModify.getPreferredSize());
		btnSubmit.setVisible(false);
		btnCancel.setVisible(false);
		EmptyComponent centerParent = new EmptyComponent();
		setLayout(new BorderLayout());
		centerParent.setLayout(new BorderLayout(0, 3));
		createCenter();
		createBottom();

		this.add(centerParent, BorderLayout.CENTER);

		if (center != null) {
			centerParent.add(center, BorderLayout.CENTER);
		}

		if (top != null) {
			centerParent.add(top, BorderLayout.NORTH);
		}

		if (bottom != null) {
			centerParent.add(bottom, BorderLayout.SOUTH);
		}

	}

	protected void resetTypes() {

	}

	public void load() {
		data = cardDAO.findAll();
		keeper.refreshStatus();
	
	}

	public void reload() {
		load();
		model.refreshUI();
	}

	protected JComponent createBottom() {

		bottom = new EmptyComponent();
		bottom.setBorder(new CompoundBorder(new EmptyBorder(0, 0, 0, 0), new LineBorder(new Color(84, 165, 213))));
		bottom.setPreferredSize(new Dimension(-1, 77));
		bottom.setLayout(new BorderLayout());
		bottom.add(createDetailComponent(), BorderLayout.CENTER);

		EmptyComponent buttonContainer = new EmptyComponent();
		buttonContainer.setLayout(new LineLayout(3, 0, 5, 0, 3, LineLayout.TRAILING, LineLayout.TRAILING, LineLayout.VERTICAL));
		buttonContainer.setPreferredSize(new Dimension(85, -1));
		buttonContainer.add(btnSubmit, LineLayout.END_FILL);

		buttonContainer.add(btnDelete, LineLayout.END_FILL);
		buttonContainer.add(btnModify, LineLayout.END_FILL);

		buttonContainer.add(btnInsert, LineLayout.END_FILL);
		buttonContainer.add(btnCancel, LineLayout.END_FILL);
		bottom.add(buttonContainer, BorderLayout.EAST);

		return bottom;
	}

	protected JComponent createCenter() {
		final Class<?>[] columnsClass = { String.class, String.class, String.class, Timestamp.class };
		final String[] getMethodsName = { "getName", "getUnit", "getDescription", "getCreated" };
		final String[] setMethodsName = { "setName", "setUnit", "setDescription", "setCreated" };
		final int[] columnsPreferredWidth = { 120, 10, 200, 120 };
		EmptyComponent ec = new EmptyComponent();
		JCScrollTable scTable = new JCScrollTable();
		table = scTable.getTable();
		model = new CommonTableModel<Card>(table, COLUMNS_NAME, columnsClass, getMethodsName, setMethodsName, data);
		TableRowSorter<CommonTableModel<Card>> sorter = new TableRowSorter<CommonTableModel<Card>>(model);

		scTable.setAlpha(0.0f);
		scTable.setColumnControlEnabled(false);
		ec.setLayout(new BorderLayout());
		ec.add(scTable, BorderLayout.CENTER);
		table.setModel(model);
		table.setDragEnabled(false);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		table.setRowSorter(sorter);
		table.setRendererOpaque(false);
		((JCTableHeader) table.getTableHeader()).setShowPopupMenu(false);
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				whenSelectionChanged(e);
			}
		});
		table.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				select(e);
			}

			public void mouseReleased(MouseEvent e) {
				showPopupMenu(e);
			}
		});

		for (int i = 0; i < columnsPreferredWidth.length; i++) {
			table.getColumnModel().getColumn(i).setPreferredWidth(columnsPreferredWidth[i]);
		}

		return center = ec;
	}

	private JComponent createDetailComponent() {
		EmptyComponent ec = new EmptyComponent();
		EmptyComponent firstRow = new EmptyComponent();

		JCLabel lbName = new JCLabel("产品名称");
		JCLabel lbUnit = new JCLabel("单位");
		JCLabel lbDesc = new JCLabel("产品描述");

		Border border = new EmptyBorder(0, 0, 0, 5);
		cpName = new JCTextField();
		cpDesc = new JCTextField();
		cpUnit = new JCTextField();

		firstRow.setLayout(new BoxLayout(firstRow, BoxLayout.X_AXIS));
		firstRow.setPreferredSize(new Dimension(-1, 25));

		firstRow.add(ecName = createTitledComponent(lbName, cpName, border, 3));
		firstRow.add(ecUnit = createTitledComponent(lbUnit, cpUnit, border, 3));
		firstRow.add(ecDesc = createTitledComponent(lbDesc, cpDesc, border, 3));

		ec.setLayout(new BorderLayout(0, 5));
		ec.setBorder(new EmptyBorder(3, 5, 2, 2));
		ec.add(firstRow, BorderLayout.NORTH);

		ecName.setPreferredSize(new Dimension(100, -1));
		ecUnit.setPreferredSize(new Dimension(35, -1));
		ecDesc.setPreferredSize(new Dimension(250, -1));

		resetTextStatus(false);

		return ec;
	}

	private JComponent createTitledComponent(JComponent titleComponent, JComponent component, Border border, int hgap) {
		EmptyComponent ec = new EmptyComponent();
		ec.setBorder(border);
		ec.setLayout(new BorderLayout(hgap, 0));
		ec.add(component, BorderLayout.CENTER);

		if (titleComponent != null) {
			ec.add(titleComponent, BorderLayout.WEST);
		}

		return ec;
	}

	private void resetDetailValues() {
		if (bottom.isVisible()) {
			if (currentData == null) {
				clearValues();
			} else {
				fillValues();
			}

			resetTextStatus(false);
			resetButtonStatus(false);
		}
	}

	private void clearValues() {
		cpName.setText(null);
		cpDesc.setText(null);
		cpUnit.setText(null);
	}

	private void fillValues() {
		cpName.setText(currentData.getName());
		cpDesc.setText(currentData.getDescription());
		cpUnit.setText(currentData.getUnit());

	}

	private void resetTextStatus(boolean editable) {
		cpName.setEditable(editable);
		cpDesc.setEditable(editable);
		cpUnit.setEditable(editable);
	}

	private void resetButtonStatus(boolean modifying) {
		this.modifying = modifying;
		btnSubmit.setVisible(modifying);
		btnCancel.setVisible(modifying);
		btnInsert.setVisible(!modifying);
		btnModify.setVisible(!modifying);
		btnDelete.setVisible(!modifying);
	}

	private void select(MouseEvent e) {
		int row = table.rowAtPoint(e.getPoint());

		if (row >= 0 && SwingUtilities.isRightMouseButton(e)) {
			table.getSelectionModel().setSelectionInterval(row, row);
		} else if (row < 0 && !SwingUtilities.isMiddleMouseButton(e)) {
			if (selectedIndex >= 0) {
				table.clearSelection();
			} else {
				resetDetailValues();
			}
		}
	}

	private void showPopupMenu(MouseEvent e) {
		if (popup != null && SwingUtilities.isRightMouseButton(e)) {
			popup.show((Component) e.getSource(), e.getX(), e.getY());
		}
	}

	private void whenSelectionChanged(ListSelectionEvent e) {
		currentData = table.getSelectedRow() < 0 ? null : model.getSelectedRowData();
		boolean selectedEmpty = (selectedIndex = table.getSelectedRow()) < 0;
		modifyAction.setEnabled(!selectedEmpty);
		deleteAction.setEnabled(!selectedEmpty);
		resetDetailValues();
	}

	protected void resetRowValues(Card card) {
		card.setName(cpName.getText().trim());
		card.setDescription(cpDesc.getText().trim());
		card.setUnit(cpUnit.getText().trim());
	}

	public void cancel() {
		cpName.setEnabled(true);
		btnSubmit.setActionCommand(null);
		resetDetailValues();
	}

	protected boolean checkInput() {
		return true;
	}

	protected boolean checkFilter(User data) {
		return true;
	}

	public void submit() {
		if (!btnSubmit.isVisible() || !checkInput()) {
			return;
		}

		String cmd = btnSubmit.getActionCommand();
		boolean insert = true;
		Card card = null;

		if (CMD_INSERT.equals(cmd)) {
			card = new Card();
			card.setName(cpName.getText().trim());
			card.setDescription(cpDesc.getText().trim());
			card.setUnit(cpUnit.getText().trim());
			card.setCreated(new Timestamp(System.currentTimeMillis()));

		} else if (CMD_MODIFY.equals(cmd)) {
			card = currentData;
			insert = false;
		}

		resetRowValues(card);

		if (checkNull(insert)) {
			if (insert) {
				cardDAO.add(card);

				model.insertRowData(card);
				int row = model.convertRowIndexesToView(model.getRowCount() - 1)[0];
				table.getSelectionModel().setSelectionInterval(row, row);
			} else {
				cardDAO.update(card);

				model.refreshRowOnView(selectedIndex);
				fillValues();
			}
			cpName.setEnabled(true);
			resetButtonStatus(false);
			resetTextStatus(false);
			btnSubmit.setActionCommand(null);
		}

	}

	private boolean checkNull(boolean insert) {
		if ("".equals(cpName.getText().trim()) || "".equals(cpUnit.getText().trim())) {

			JCMessageBox.createErrorMessageBox(keeper.getMainFrame(), "必填项为空", "请输入所有必填项").open();

			cpName.requestFocus();
			return false;
		}
		if (insert) {
			if (cardDAO.findByPK(cpName.getText().trim()) != null) {
				JCMessageBox.createErrorMessageBox(keeper.getMainFrame(), "产品已经存在", "产品已经存在,请核对!").open();

				cpName.requestFocus();
				return false;
			}
		}

		return true;
	}

	public void insertOrModify(boolean insert) {
		if (modifying) {
			cancel();
		}

		btnSubmit.setActionCommand(insert ? CMD_INSERT : CMD_MODIFY);
		resetTextStatus(true);
		resetButtonStatus(true);

		if (insert) {
			cpName.setEnabled(true);
			clearValues();
			cpName.requestFocus();
		} else {
			cpName.setEnabled(false);
		}
	}

	public void delete() {
		if (!hasUsed()) {
			String message = "\u786E\u5B9A\u8981\u5220\u9664\u8BE5\u8BB0\u5F55\u5417\uFF1F";
			JCMessageBox box = JCMessageBox.createQuestionMessageBox(keeper.getMainFrame(), "\u5220\u9664", message);

			if (box.open() == JCMessageBox.YES_OPTION) {
				cardDAO.delete(currentData);
				model.delRowOnViewAt(selectedIndex);
			}
		}

	}

	private boolean hasUsed() {
		String name = currentData.getName();
		List<Composite> list = compositeDAO.findAll();
		boolean used = false;

		for (Composite composite : list) {
			if (composite.getName().contains(name)) {
				used = true;
				break;
			}
		}
		if (used) {
			JCMessageBox.createErrorMessageBox(keeper.getMainFrame(), "已经被使用", "该元件已经被使用,不能删除!").open();
		}
		return used;
	}

	public List<Card> getAllData() {
		return data;
	}

	@Override
	public String getType() {
		return "产品管理";
	};

	@Override
	public void refresh() {
		load();
		this.center.repaint();
		
		keeper.refreshStatus();
	}
}
